@@ -14,6 +14,7 @@ pm_to_blib
Makefile.old
semantic.cache
templates-Pro/json
+templates-Pro/json-cs
getoptint.re2c.inc
resetopt0.inc
resetoptnot0.inc
@@ -293,3 +293,9 @@ Revision history for Perl extension HTML::Template::Pro.
09502 Fri Jun 18 18:02:28 EEST 2010
- bugfix release: segfault for string operetions
with undefined variables. Thanks to Mike Shogin.
+
+09503 Sat Aug 28 18:00:49 EEST 2010
+ - log file is not truncated now in tmplpro_set_log_file.
+ - freed memory access error fixed.
+ - perl: CommonTest.pm hidden from installation
+ - tests: added generic json-packed test data
@@ -27,7 +27,6 @@ exprtype.h
exprval.h
lib/HTML/Template/PerlInterface.pod
lib/HTML/Template/Pro.pm
-lib/HTML/Template/Pro/CommonTest.pm
lib/HTML/Template/Pro/WrapAssociate.pm
lib/HTML/Template/SYNTAX.pod
loadfile.h
@@ -65,9 +64,11 @@ t/03complex.t
t/04register.t
t/05path_like_variable_scope.t
t/06loop_var.t
+t/error_output.t
t/HTML-Template-Expr.t
t/HTML-Template-Pro.t
t/HTML-Template.t
+t/HTML/Template/Pro/CommonTest.pm
t/magic.t
t/pod.t
t/realloc.t
@@ -1,6 +1,6 @@
--- #YAML:1.0
name: HTML-Template-Pro
-version: 0.9502
+version: 0.9503
abstract: Perl/XS module to use HTML Templates from CGI scripts
author:
- I. Yu. Vlasenko <viy@altlinux.org>
@@ -1,4 +1,4 @@
-HTML-Template-Pro version 0.9502
+HTML-Template-Pro version 0.9503
==============================
DESCRIPTION
@@ -14,7 +14,7 @@ typedef struct exprval (*func_t_ee) (struct expr_parser* exprobj, struct exprval
struct symrec_const
{
char *name; /* name of symbol */
- int len; /* symbol length */;
+ int len; /* symbol length */
int type; /* type of symbol: either VAR or FNCT */
double var; /* value of a VAR */
void* fnctptr; /* value of a FNCT */
@@ -37,7 +37,7 @@ static void BACKCALL stub_write_chars_to_pbuffer (ABSTRACT_WRITER* state,const c
}
static ABSTRACT_USERFUNC* BACKCALL stub_is_expr_userfnc_func (ABSTRACT_FUNCMAP* af, PSTRING name) {
- tmpl_log(TMPL_LOG_ERROR,"is_expr_userfnc_func stub: EXPR is not initialized properly. user func dispatcher was not supplied.");
+ tmpl_log(TMPL_LOG_DEBUG,"is_expr_userfnc_func stub: EXPR is not initialized properly. user func dispatcher was not supplied.\n");
return NULL;
}
@@ -1,161 +0,0 @@
-package HTML::Template::Pro::CommonTest;
-
-use strict;
-use warnings;
-use Carp;
-
-use Test;
-use File::Spec;
-use File::Path;
-use HTML::Template::Pro qw/:const/;
-#use Data::Dumper;
-use JSON;
-require Exporter;
-use vars qw/@ISA @EXPORT/;
-@ISA=qw/Exporter/;
-@EXPORT =qw/test_tmpl test_tmpl_std test_tmpl_expr dryrun/;
-
-use vars qw/$DumpDir/;
-$DumpDir='json';
-
-#$Data::Dumper::Terse=1;
-#$Data::Dumper::Indent=1;
-#$Data::Dumper::Useqq=1;
-#$Data::Dumper::Pair = ' : ';
-
-#########################
-
-my $DEBUG=$ENV{HTP_DEBUG};
-$DEBUG||=0;
-
-sub test_tmpl {
- my $file=shift;
- my $optref=shift;
- my @param=@_;
- my $tmpl;
- print "\n--------------- Test: $file ---------------------\n";
- chdir 'templates-Pro';
- $tmpl=HTML::Template::Pro->new(filename=>$file.'.tmpl',debug=>$DEBUG, @$optref);
- $tmpl->param(@param);
- &dryrun($tmpl,$file);
- $ENV{HTP_DUMP} && &dump_test ($file,{@$optref},{@param});
- chdir '..';
-}
-
-sub test_tmpl_expr {
- my $file=shift;
- my $tmpl;
- print "\n--------------- Test: $file ---------------------\n";
- chdir 'templates-Pro';
- $tmpl=HTML::Template::Pro->new(filename=>$file.'.tmpl', loop_context_vars=>1, case_sensitive=>1,tmpl_var_case=>ASK_NAME_UPPERCASE|ASK_NAME_AS_IS,debug=>$DEBUG, functions=>{'hello' => sub { return "hi, $_[0]!" }});
- $tmpl->param(@_);
- # per-object extension
- $tmpl->register_function('per_object_call' => sub { return shift()."-arg"});
- $tmpl->register_function('perobjectcall2' => sub { return shift()."-arg"});
- &dryrun($tmpl,$file);
- chdir '..';
-}
-
-my $case_ext = [
- loop_context_vars=>1,
- case_sensitive=>0,
- ];
-my $case_int = [
- loop_context_vars=>1,
- case_sensitive=>1,
- tmpl_var_case=>ASK_NAME_UPPERCASE,
- ];
-
-sub test_tmpl_std {
- my ($file,@args)=@_;
- &test_tmpl($file, $case_ext, @args);
- &test_tmpl($file, $case_int, @args);
-}
-
-sub dryrun {
- my $tmpl=shift;
- my $file=shift;
- open (OUTFILE, ">$file.raw") || die "can't open $file.raw: $!";
- binmode (OUTFILE);
- $tmpl->output(print_to => *OUTFILE);
- close (OUTFILE) || die "can't close $file.raw: $!";
- my $fileout = &catfile("$file.out");
- my $files_equal=&catfile("$file.raw") eq $fileout;
- if ($files_equal) {
- ok($files_equal) && unlink "$file.raw";
- } else {
- if (-x '/usr/bin/diff') {
- print STDERR `diff -u $file.out $file.raw`;
- } else {
- print STDERR "# >>> ---$file.raw---\nTODO: diff here\n>>> ---end $file.raw---\n";
- }
- }
- my $output=$tmpl->output();
- ok (defined $output and $output eq $fileout);
-}
-
-sub catfile {
- my $file=shift;
- open (INFILE, $file) || die "can't open $file: $!";
- binmode (INFILE);
- local $/;
- my $catfile=<INFILE>;
- close (INFILE) || die "can't close $file: $!";
- return $catfile;
-}
-
-my %filename_counter;
-$0=~/([\w_-]+)(?:\.t)$/;
-my $dump_prefix = $1 ? "$1-" : '';
-sub _dump_file_name {
- my ($file) = @_;
- my $plain=$file;
- $plain=~s![\\/:]!_!g;
- return File::Spec->catfile($DumpDir,
- $dump_prefix.$plain.'-'.sprintf("%.2d",++$filename_counter{$file}).'.json');
-}
-
-sub dump_test {
- my ($file,$optref,$paramref) = @_;
- mkpath ($DumpDir);
- my $dump_file = _dump_file_name($file);
- open FH, '>', $dump_file or die "can't open ($!) ".$dump_file;
- my $tojson = {
- 'file' => $file,
- 'options' => $optref,
- 'params' => $paramref,
- };
- print FH to_json($tojson, {utf8 => 1, pretty => 1});
- close (FH) or die "can't close ($!) ".$dump_file;
-}
-
-### Local Variables:
-### mode: perl
-### End:
-
-
-1;
-
-__END__
-
-#head1 NAME
-
-HTML::Template::Pro::CommonTest - internal common test library
-
-#head1 DESCRIPTION
-
-internal common test library
-
-#head1 AUTHOR
-
-I. Vlasenko, E<lt>viy@altlinux.orgE<gt>
-
-#head1 COPYRIGHT AND LICENSE
-
-Copyright (C) 2009 by I. Yu. Vlasenko.
-
-This library is free software; you can redistribute it and/or modify it under
-either the LGPL2+ or under the same terms as Perl itself, either Perl version 5.8.4
-or, at your option, any later version of Perl 5 you may have available.
-
-#cut
@@ -12,7 +12,7 @@ require Exporter;
use vars qw($VERSION @ISA @EXPORT_OK %EXPORT_TAGS);
@ISA = qw(DynaLoader Exporter);
-$VERSION = '0.9502';
+$VERSION = '0.9503';
@EXPORT_OK = qw/ASK_NAME_DEFAULT ASK_NAME_AS_IS ASK_NAME_LOWERCASE ASK_NAME_UPPERCASE ASK_NAME_MASK/;
%EXPORT_TAGS = (const => [qw/ASK_NAME_DEFAULT ASK_NAME_AS_IS ASK_NAME_LOWERCASE ASK_NAME_UPPERCASE ASK_NAME_MASK/]);
@@ -139,8 +139,8 @@ mmap_load_file (const char* filepath) {
stream = fopen(filepath, "r");
if (stream == NULL) return memarea; /* {NULL,NULL} */
/* mmap size_in_bytes+1 to avoid crash with empty file */
- memarea.begin=(char*) malloc(memsize+1);
- writepoint=memarea.begin;
+ memarea.begin=(const char*) malloc(memsize+1);
+ writepoint=(char*)memarea.begin;
while (1) {
realsize=fread(writepoint, 1, chunksize, stream);
@@ -149,8 +149,8 @@ mmap_load_file (const char* filepath) {
writepoint+=chunksize;
if (size_in_bytes+chunksize>memsize) {
memsize*=2;
- memarea.begin=(char*) realloc(memarea.begin, memsize+1);
- writepoint=memarea.begin+size_in_bytes;
+ memarea.begin=(char*) realloc((char*)memarea.begin, memsize+1);
+ writepoint=((char*)memarea.begin)+size_in_bytes;
}
} else {
fclose(stream);
@@ -164,7 +164,7 @@ static
int
mmap_unload_file (PSTRING memarea) {
/* destroying */
- free(memarea.begin);
+ free((char*)memarea.begin);
return 0;
}
@@ -7,6 +7,7 @@
#define ERR_PRO_FILE_NOT_FOUND 2
#define ERR_PRO_CANT_OPEN_FILE 3
#define ERR_PRO_TEMPLATE_SYNTAX_ERROR 4
+#define ERR_PRO_NOT_ENOUGH_MEMORY 5
#endif /* pconst.h */
@@ -6,7 +6,7 @@
%define module HTML-Template-Pro
Name: perl-%module
-Version: 0.9502
+Version: 0.9503
Release: alt1
Packager: Igor Yu. Vlasenko <viy@altlinux.org>
@@ -54,6 +54,9 @@ in the Perl script.
%perl_vendor_man3dir/*
%changelog
+* Sat Aug 28 2010 Igor Vlasenko <viy@altlinux.ru> 0.9503-alt1
+- new version; see Changes
+
* Thu Jun 17 2010 Igor Vlasenko <viy@altlinux.ru> 0.9502-alt1
- new version; see Changes
@@ -429,6 +429,7 @@ tmplpro_exec_tmpl_filename (struct tmplpro_param *param, const char* filename)
int mmapstatus;
PSTRING memarea;
int retval = 0;
+ const char* saved_masterpath;
/*
* param->masterpath is path to upper level template
* (or NULL in toplevel) which called <include filename>.
@@ -439,7 +440,8 @@ tmplpro_exec_tmpl_filename (struct tmplpro_param *param, const char* filename)
if (NULL==filepath) return ERR_PRO_FILE_NOT_FOUND;
/* filepath should be alive for every nested template */
filepath = strdup(filepath);
-
+ if (NULL==filepath) return ERR_PRO_NOT_ENOUGH_MEMORY;
+ saved_masterpath=param->masterpath; /* saving current file name */
param->masterpath=filepath;
if (param->filters) memarea=(param->LoadFileFuncPtr)(param->ext_filter_state,filepath);
else memarea=mmap_load_file(filepath);
@@ -460,6 +462,7 @@ tmplpro_exec_tmpl_filename (struct tmplpro_param *param, const char* filename)
else mmapstatus=mmap_unload_file(memarea);
cleanup_filepath:
if (filepath!=NULL) free((void*) filepath);
+ param->masterpath=saved_masterpath;
return retval;
}
@@ -468,12 +471,16 @@ int
tmplpro_exec_tmpl_scalarref (struct tmplpro_param *param, PSTRING memarea)
{
struct tmplpro_state state;
+ const char* saved_masterpath=param->masterpath; /* saving current file name */
param->masterpath=NULL; /* no upper file */
state.top = memarea.begin;
state.next_to_end=memarea.endnext;
- if (memarea.begin == memarea.endnext) return 0;
- init_state(&state,param);
- process_state(&state);
+ if (memarea.begin != memarea.endnext) {
+ init_state(&state,param);
+ process_state(&state);
+ }
+ /* exit cleanup code */
+ param->masterpath=saved_masterpath;
return 0;
}
@@ -694,7 +701,7 @@ tmplpro_set_log_file(struct tmplpro_param* param, const char* logfilename)
tmpl_log_set_callback(tmpl_log_default_callback);
return 0;
}
- file_p = fopen(logfilename, "w");
+ file_p = fopen(logfilename, "a");
if (!file_p) {
tmpl_log(TMPL_LOG_ERROR,"tmplpro_set_log_file: can't create log file [%s]\n",logfilename);
return ERR_PRO_FILE_NOT_FOUND;
@@ -12,7 +12,11 @@ static const char* const errlist[] = {
"invalid argument",
"file not found",
"can't open file",
- "syntax error in template"
+ "syntax error in template",
+ "not enough memory (allocation error)",
+ "",
+ "",
+ ""
};
/*
@@ -0,0 +1,172 @@
+package HTML::Template::Pro::CommonTest;
+
+use strict;
+use warnings;
+use Carp;
+
+use Test;
+use File::Spec;
+use File::Path;
+use HTML::Template::Pro qw/:const/;
+#use Data::Dumper;
+use JSON;
+require Exporter;
+use vars qw/@ISA @EXPORT/;
+@ISA=qw/Exporter/;
+@EXPORT =qw/test_tmpl test_tmpl_std test_tmpl_expr dryrun/;
+
+use vars qw/$DumpDir $DumpDir_no_cs/;
+$DumpDir='json-cs';
+$DumpDir_no_cs='json';
+
+#$Data::Dumper::Terse=1;
+#$Data::Dumper::Indent=1;
+#$Data::Dumper::Useqq=1;
+#$Data::Dumper::Pair = ' : ';
+
+#########################
+
+my $DEBUG=$ENV{HTP_DEBUG};
+$DEBUG||=0;
+
+sub test_tmpl {
+ my $file=shift;
+ my $optref=shift;
+ my @param=@_;
+ my $tmpl;
+ print "\n--------------- Test: $file ---------------------\n";
+ chdir 'templates-Pro';
+ $tmpl=HTML::Template::Pro->new(filename=>$file.'.tmpl',debug=>$DEBUG, @$optref);
+ $tmpl->param(@param);
+ &dryrun($tmpl,$file);
+ $ENV{HTP_DUMP} && &dump_test ($file,{@$optref},{@param});
+ chdir '..';
+}
+
+sub test_tmpl_expr {
+ my $file=shift;
+ my $tmpl;
+ print "\n--------------- Test: $file ---------------------\n";
+ chdir 'templates-Pro';
+ $tmpl=HTML::Template::Pro->new(filename=>$file.'.tmpl', loop_context_vars=>1, case_sensitive=>1,tmpl_var_case=>ASK_NAME_UPPERCASE|ASK_NAME_AS_IS,debug=>$DEBUG, functions=>{'hello' => sub { return "hi, $_[0]!" }});
+ $tmpl->param(@_);
+ # per-object extension
+ $tmpl->register_function('per_object_call' => sub { return shift()."-arg"});
+ $tmpl->register_function('perobjectcall2' => sub { return shift()."-arg"});
+ &dryrun($tmpl,$file);
+ chdir '..';
+}
+
+my $case_ext = [
+ loop_context_vars=>1,
+ case_sensitive=>0,
+ ];
+my $case_int = [
+ loop_context_vars=>1,
+ case_sensitive=>1,
+ tmpl_var_case=>ASK_NAME_UPPERCASE,
+ ];
+
+sub test_tmpl_std {
+ my ($file,@args)=@_;
+ &test_tmpl($file, $case_ext, @args);
+ &test_tmpl($file, $case_int, @args);
+}
+
+sub dryrun {
+ my $tmpl=shift;
+ my $file=shift;
+ open (OUTFILE, ">$file.raw") || die "can't open $file.raw: $!";
+ binmode (OUTFILE);
+ $tmpl->output(print_to => *OUTFILE);
+ close (OUTFILE) || die "can't close $file.raw: $!";
+ my $fileout = &catfile("$file.out");
+ my $files_equal=&catfile("$file.raw") eq $fileout;
+ if ($files_equal) {
+ ok($files_equal) && unlink "$file.raw";
+ } else {
+ if (-x '/usr/bin/diff') {
+ print STDERR `diff -u $file.out $file.raw`;
+ } else {
+ print STDERR "# >>> ---$file.raw---\nTODO: diff here\n>>> ---end $file.raw---\n";
+ }
+ }
+ my $output=$tmpl->output();
+ ok (defined $output and $output eq $fileout);
+}
+
+sub catfile {
+ my $file=shift;
+ open (INFILE, $file) || die "can't open $file: $!";
+ binmode (INFILE);
+ local $/;
+ my $catfile=<INFILE>;
+ close (INFILE) || die "can't close $file: $!";
+ return $catfile;
+}
+
+my %filename_counter;
+$0=~/([\w_-]+)(?:\.t)$/;
+my $dump_prefix = $1 ? "$1-" : '';
+sub _dump_file_name {
+ my ($DumpDir,$file) = @_;
+ my $plain=$file;
+ $plain=~s![\\/:]!_!g;
+ return File::Spec->catfile($DumpDir,
+ $dump_prefix.$plain.'-'.sprintf("%.2d",++$filename_counter{$file}).'.json');
+}
+
+sub dump_test {
+ my ($file,$optref,$paramref) = @_;
+ mkpath ([$DumpDir,$DumpDir_no_cs]);
+ my $tojson = {
+ 'file' => $file,
+ 'options' => $optref,
+ 'params' => $paramref,
+ };
+ &__dump_json(&_dump_file_name($DumpDir,$file), $tojson);
+ my $case_sensitive=$optref->{'case_sensitive'};
+ if (defined $case_sensitive) {
+ delete $optref->{'case_sensitive'};
+ $optref->{'tmpl_var_case'}=ASK_NAME_UPPERCASE unless $case_sensitive;
+ }
+ &__dump_json(&_dump_file_name($DumpDir_no_cs,$file), $tojson);
+}
+
+sub __dump_json {
+ my ($dump_file, $tojson) = @_;
+ open FH, '>', $dump_file or die "can't open ($!) ".$dump_file;
+ print FH to_json($tojson, {utf8 => 1, pretty => 1});
+ close (FH) or die "can't close ($!) ".$dump_file;
+}
+
+### Local Variables:
+### mode: perl
+### End:
+
+
+1;
+
+__END__
+
+#head1 NAME
+
+HTML::Template::Pro::CommonTest - internal common test library
+
+#head1 DESCRIPTION
+
+internal common test library
+
+#head1 AUTHOR
+
+I. Vlasenko, E<lt>viy@altlinux.orgE<gt>
+
+#head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2009 by I. Yu. Vlasenko.
+
+This library is free software; you can redistribute it and/or modify it under
+either the LGPL2+ or under the same terms as Perl itself, either Perl version 5.8.4
+or, at your option, any later version of Perl 5 you may have available.
+
+#cut
@@ -8,6 +8,7 @@
use Test;
BEGIN { plan tests => 1+4*8+2*7 };
use HTML::Template::Pro;
+use lib "t";
use HTML::Template::Pro::CommonTest;
ok(1); # If we made it this far, we're ok.
@@ -14,6 +14,7 @@ BEGIN {
}
use File::Spec;
use HTML::Template::Pro;
+use lib "t";
use HTML::Template::Pro::CommonTest;
ok(1); # If we made it this far, we're ok.
@@ -0,0 +1,19 @@
+#!/usr/bin/perl -w
+use Test::More no_plan;
+use HTML::Template::Pro;
+
+my $src1 =<<"END;";
+</TMPL_IF>
+<tmpl_var EXPR="(a/(foo&&&">
+<TMPL_IF NAME="foo>
+<TMPL_FI NAME="foo>
+name foo
+END;
+
+my $template1 = HTML::Template::Pro->new(scalarref => \$src1, debug=> -1);
+$template1->param(foo => 1);
+my $out=$template1->output();
+#print $out;
+ok(1); # not crashed
+
+__END__
@@ -184,7 +184,6 @@ tag_handler_include (struct tmplpro_state *state, const PSTRING* const TagOptVal
{
struct tmplpro_param* param;
char* filename;
- const char* masterpath;
int x;
PSTRING varvalue;
PSTRING defvalue;
@@ -209,16 +208,17 @@ tag_handler_include (struct tmplpro_state *state, const PSTRING* const TagOptVal
};
if (varvalue.begin==varvalue.endnext && defvalue.begin!=defvalue.endnext) varvalue=defvalue;
/* pstrdup */
- filename =(char*) malloc(varvalue.endnext-varvalue.begin+1);
- for (x=0;x<varvalue.endnext-varvalue.begin;x++) {
- *(filename+x)=*(varvalue.begin+x);
+ {
+ const long len = varvalue.endnext-varvalue.begin;
+ filename =(char*) malloc(len+1);
+ for (x=0;x<len;x++) {
+ *(filename+x)=*(varvalue.begin+x);
+ }
+ *(filename+len)=0;
}
- *(filename+(varvalue.endnext-varvalue.begin))=0;
/* end pstrdup */
- masterpath=param->masterpath; /* saving current file name */
tmplpro_exec_tmpl_filename (param,filename);
free (filename);
- param->masterpath=masterpath;
param->cur_includes--;
return;
}
@@ -1,3 +1,5 @@
<H1> test_esc4 </H1>
\\<>\"; %FAhidden:\r\nend
+VAR1
+Some"' Txt'
@@ -2,3 +2,5 @@
<tmpl_iF VAR4> <tmpl_var escape="JS" DEFAULT="test failed" NAME="STUFF1">
<tmpl_else> <tmpl_var DEFault="test failed" name="STUFF1" ESCApe='js'>
</tmpl_if>
+<tmpl_var name='VAR1' escape='html'>
+<tmpl_var name='STUFF2' escape='html'>